package com.job.service.impl;

import com.job.common.Constant;
import com.job.common.RedisKey;
import com.job.common.ResponseResult;
import com.job.common.enums.ResultCodeEnum;
import com.job.common.exception.AvatarUpdateException;
import com.job.common.exception.LoginException;
import com.job.common.exception.RegisterException;
import com.job.common.exception.UserUpdateException;
import com.job.controller.req.LoginVo;
import com.job.controller.req.RegisterReqVO;
import com.job.controller.req.hrCorporationBandReqVO;
import com.job.mapper.CorporationMapper;
import com.job.mapper.HrMapper;
import com.job.mapper.StudentMapper;
import com.job.mapper.UserMapper;
import com.job.pojo.*;
import com.job.service.LoginService;
import com.job.util.JwtUtil;
import com.job.util.OssUtil;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements LoginService, RedisKey , Constant {

    @Resource
    private UserMapper userMapper;

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private RedisTemplate<String,Object> redisTemplate;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private StudentMapper studentMapper;

    @Resource
    private HrMapper hrMapper;

    @Resource
    private CorporationMapper corporationMapper;

    @Override
    public ResponseResult<Map<String,String>> login(LoginVo loginVo) throws LoginException {
        UsernamePasswordAuthenticationToken authenticationToken
                = new UsernamePasswordAuthenticationToken(loginVo.getUserName(),loginVo.getPassword());
        Authentication authenticate = null;
        //账号密码不对这里会抛异常
        try {
             authenticate = authenticationManager.authenticate(authenticationToken);
        }catch (RuntimeException e){
            throw new LoginException();
        }

        //使用userid生成token
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        String userId = loginUser.getUser().getId().toString();
        String jwt =  JwtUtil.createJWT(userId);

        //authenticate存入redis
        redisTemplate.opsForValue().set(RedisKey.LOGIN_PREFIX + RedisKey.SEPARATE + userId,loginUser
                ,REDIS_TTL, TimeUnit.DAYS);

        //把token响应给前端
        Map<String,String> map = new HashMap<>();
        if (loginUser.getUser().getUserType() == STUDENT){
            map.put("studentId",loginUser.getUser().getRoleId().toString());
        }else if (loginUser.getUser().getUserType() == HR){
            map.put("hrId",loginUser.getUser().getRoleId().toString());
        }
        map.put("userId",loginUser.getUser().getId().toString());
        map.put("token",jwt);
        map.put("title",loginUser.getUser().getAvatar());
        return new ResponseResult<Map<String,String>>(200,"登录成功",map);
    }

    @Override
    public ResponseResult<ResultCodeEnum> logout() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        Long userid = loginUser.getUser().getId();
        redisTemplate.delete(RedisKey.LOGIN_PREFIX + RedisKey.SEPARATE + userid);
        return new ResponseResult<ResultCodeEnum>().success();
    }

    @Transactional(rollbackFor = AvatarUpdateException.class)
    @Override
    public ResponseResult<String> uploadTitle(MultipartFile file,Integer userId) throws IOException
            , AvatarUpdateException {
        COSClient cosClient = OssUtil.getOssClient();
        //获取上传文件输入流
        InputStream inputStream = file.getInputStream();
        //获取文件名称
        String fileName = file.getOriginalFilename();
        String substring = fileName.substring(fileName.lastIndexOf("."));
        fileName = TITLE + "/" + userId + substring;
        com.qcloud.cos.model.ObjectMetadata objectMetadata = new ObjectMetadata();
        PutObjectRequest putObjectRequest =
                new PutObjectRequest(BUCKET_NAME, fileName, inputStream,objectMetadata);
        cosClient.putObject(putObjectRequest);
        cosClient.shutdown();

        String url = "https://"+BUCKET_NAME+"."+"cos"+"."+END_POINT+".myqcloud.com"+"/"+fileName;
        User user = userMapper.selectById(userId);
        if (Objects.isNull(user)){
            throw new AvatarUpdateException("头像修改失败");
        }
        user.setAvatar(url);
        if(userMapper.updateById(user) < 1){
            throw new AvatarUpdateException("头像修改失败");
        }
        return new ResponseResult<String>().success(fileName);
    }

    @Override
    @Transactional
    public ResponseResult<Long> register(RegisterReqVO registerReqVO) throws RegisterException {
        User user = new User();
        String password = passwordEncoder.encode(registerReqVO.getPassword());
        user.setUserName(registerReqVO.getUserName());
        user.setPassword(password);
        user.setUserType(registerReqVO.getUserType());
        user.setCreateTime(LocalDateTime.now());

        //判断用户类型
        if (registerReqVO.getUserType() == 1){
            Student student = new Student();
            student.setWechat("wx");
            if (studentMapper.insert(student) < 1){
                throw new RegisterException("注册失败");
            }
            user.setRoleId(student.getStudentId());
        }else if (registerReqVO.getUserType() == 2){
            Hr hr = new Hr();
            hr.setCorporationId(1);
            if (hrMapper.insert(hr) < 1){
                throw new RegisterException("注册失败");
            }
            user.setRoleId(hr.getHrId());
        }
        if (userMapper.insert(user) < 1){
            throw new RegisterException("注册失败");
        }
        return registerReqVO.getUserType() ==  HR ? new ResponseResult<Long>().success(user.getId())
                : new ResponseResult<Long>().success(Long.valueOf(STUDENT));
    }


    @Override
    @Transactional(rollbackFor = UserUpdateException.class)
    public ResponseResult<ResultCodeEnum> hrCorporationBand(hrCorporationBandReqVO hrCorporationBandReqVO)
            throws UserUpdateException {
        //访问这个接口肯定是hr
        Integer userId = hrCorporationBandReqVO.getUserId();
        User user = userMapper.selectById(userId);
        Integer roleId = user.getRoleId();
        Hr hr = hrMapper.selectById(roleId);

        hr.setCorporationId(hrCorporationBandReqVO.getCorporationId());
        Corporation corporation = corporationMapper.selectById(hrCorporationBandReqVO.getCorporationId());
        if (Objects.isNull(corporation)){
           return new ResponseResult<ResultCodeEnum>().fail(ResultCodeEnum.CORPORATION_IS_NULL_FAIL);
        }
        hr.setHrName(corporation.getCorporation() + "招聘者");
        user.setNickName(hr.getHrName());

        if (hrMapper.updateById(hr) < 1 || userMapper.updateById(user) < 1){
            throw new UserUpdateException("公司信息绑定失败");
        }
        return new ResponseResult<ResultCodeEnum>().success();
    }
}
